package com.lihao.walkers.surfaceview;

import java.util.List;

import com.lihao.walkers.map.LocationBean;
import com.lihao.walkers.utils.Utils;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.View;

/**
 * 目标跟踪view。
 * @author lihao
 */
public class TargetView extends View {

	/** 绘制时候的半径。 */
	private int mDrawRadius = -1;

	/** 绘图区中心X坐标。 */
	private float mCenterX = -1;

	/** 绘图区中心Y坐标。 */
	private float mCenterY = -1;

	/** 文字字号。 */
	private float mTextSize = -1;

	/** 文字字体高度。 */
	private float mTextHeight = -1;

	/** 是否绘制圆形。 */
	private boolean mDrawCircle = false;

	/** 是否绘制数据。 */
	private boolean mDrawData = false;

	/** 绘制圆形需要的画笔。 */
	private Paint mCirclePaint = null;

	/** 绘制位置数据需要的画笔。 */
	private Paint mLocationPaint = null;

	/** 初始纬度。 */
	private double mStartLat = -1;

	/** 初始经度。 */
	private double mStartLon = -1;

	/** 列表数据。 */
	private List<LocationBean> mLocationList = null;

	/** 单一数据。 */
	private LocationBean mSingleLocation = null;

	/** 要跟踪的目标点中的最远距离。 */
	private double mMaxDistance = -1;

	/** 手机本身与正北方向的偏差角度。 */
	private float mSelfAngle = 0;

	public TargetView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initPaints();
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if(mDrawData){
			drawData(canvas);
		}
		if(mDrawCircle){
			drawCircle(canvas);
		}
	}

	/**
	 * 设置文字字号。
	 * @param textSize 文字字号。
	 */
	public void setTextSize(float textSize){
		mTextSize = textSize;
		mLocationPaint.setTextSize(mTextSize);
		mTextHeight = Utils.getInstance().getTextHeight(mLocationPaint);
	}

	/**
	 * 初始经纬度设置。
	 * @param startLat 初始纬度。
	 * @param startLon 初始经度。
	 */
	public void initStartLocation(double startLat, double startLon){
		mStartLat = startLat;
		mStartLon = startLon;
	}

	/**
	 * 初始化跟踪框。
	 */
	public void initTracking(){
		mCenterX = getLayoutParams().width >> 1;
		mCenterY = getLayoutParams().height >> 1;
		mDrawRadius = Math.min(getLayoutParams().width, getLayoutParams().height) >> 1;
		mDrawCircle = true;
		mDrawData = true;
		postInvalidate();
	}

	/**
	 * 设置列表数据。
	 * @param locationList 地理位置列表。
	 */
	public void setData(List<LocationBean> locationList){
		clearOldData();
		mLocationList = locationList;
		calculateMaxDistace();
	}

	/**
	 * 设置单一数据。
	 * @param singleLocation 单一数据。
	 */
	public void setData(LocationBean singleLocation){
		clearOldData();
		mSingleLocation = singleLocation;
		calculateMaxDistace();
	}

	/**
	 * 设置手机本身与正北方向的偏差。
	 * @param selfAngle 手机本身与正北方向的偏差。
	 */
	public void setSelfAngle(float selfAngle){
		mSelfAngle = selfAngle;
	}

	/**
	 * 更新跟踪view。
	 */
	public void upgradeTracking(){
		postInvalidate();
	}

	/**
	 * 初始化画笔。
	 */
	private void initPaints(){
		// 圆圈用到的画笔。
		mCirclePaint = new Paint();
		mCirclePaint.setAntiAlias(true);
		mCirclePaint.setStrokeWidth(2.0f);
		// 绘制地理位置数据用到的画笔。
		mLocationPaint = new Paint();
		mLocationPaint.setAntiAlias(true);
	}

	/**
	 * 绘制视野范围圆形。
	 * @canvas 画布。
	 */
	private void drawCircle(Canvas canvas){
		mCirclePaint.setColor(Color.BLUE);
		mCirclePaint.setStyle(Style.FILL);
		canvas.drawCircle(mCenterX, mCenterY, 4.0f, mCirclePaint);
	}

	/**
	 * 绘制坐标数据。
	 * @param canvas 画布。
	 */
	private void drawData(Canvas canvas){
		if(mSingleLocation != null){ // 只有一个坐标点需要绘制。
			drawOneData(canvas, mSingleLocation.name, mStartLat, mStartLon,
					mSingleLocation.getLatitude(), mSingleLocation.getLongitude());
		} else { // 需要绘制多个点。
			int i = 0;
			int count = mLocationList.size();
			for (; i < count; i++) {
				LocationBean oneBean = mLocationList.get(i);
				drawOneData(canvas, oneBean.name, mStartLat, mStartLon,
						oneBean.getLatitude(), oneBean.getLongitude());
			}
		}
	}

	/**
	 * 清理老数据。
	 */
	private void clearOldData(){
		if(mLocationList != null){
			mLocationList.clear();
			mLocationList = null;
		}
		mSingleLocation = null;
	}

	/**
	 * 计算给定的坐标点中的最远距离。
	 */
	private void calculateMaxDistace(){
		mMaxDistance = -1; // 计算之前先将旧数据清空。
		if(mSingleLocation != null){
			mMaxDistance = Utils.getInstance().calculateDistance(
					mStartLat, mStartLon,
					mSingleLocation.getLatitude(), mSingleLocation.getLongitude());
		} else {
			int i = 0;
			int locationCount = mLocationList.size();
			for (; i < locationCount; i++) {
				mMaxDistance = Math.max(mMaxDistance,
						Utils.getInstance().calculateDistance(
								mStartLat, mStartLon,
								mLocationList.get(i).getLatitude(),
								mLocationList.get(i).getLongitude()));
			}
		}
	}

	/**
	 * 绘制一个位置数据。
	 * @param canvas 画布。
	 * @param text 要绘制的文字。
	 * @param startLat 开始纬度。
	 * @param startLon 开始经度。
	 * @param targetLat 结束纬度。
	 * @param targetLon 结束经度。
	 */
	private void drawOneData(Canvas canvas, String text,
							 double startLat, double startLon,
							 double targetLat, double targetLon){
		// 计算实际距离。
		double targetDistance = Utils.getInstance().calculateDistance(
				mStartLat, mStartLon, targetLat, targetLon);
		// 计算偏移角度。
		double targetAngle = Utils.getInstance().calculateAngle(
				mStartLat, mStartLon, targetLat, targetLon);
		// 需要减掉手机本身相对于正北方的偏移角度。
		targetAngle = targetAngle - mSelfAngle;
		// 换算成手机屏幕上的距离。
		double perDistance = mDrawRadius * (targetDistance / mMaxDistance);
		// 计算X坐标。
		float perX = (float) (mCenterX + perDistance * Math.sin(targetAngle * Math.PI / 180));
		float perY = (float) (mCenterY - perDistance * Math.cos(targetAngle * Math.PI / 180));
		String distance = String.valueOf(targetDistance);
		float textWidth = mLocationPaint.measureText(text); // 文字宽度。
		float distanceWidth = mLocationPaint.measureText(distance); // 距离宽度。
		// 绘制一个矩形背景。
		float tipWidth = Math.max(textWidth, distanceWidth);
		mLocationPaint.setColor(Color.BLACK);
		mLocationPaint.setAlpha(128);
		canvas.drawRect(perX - tipWidth / 2.0f - 1.0f, perY - mTextHeight - 1.0f,
				perX + tipWidth / 2.0f + 1.0f, perY + mTextHeight + 1.0f, mLocationPaint);
		// 绘制位置文字提示。
		mLocationPaint.setColor(Color.YELLOW);
		mLocationPaint.setAlpha(255);
		canvas.drawText(text, perX - mLocationPaint.measureText(text) / 2.0f,
				perY - mTextHeight * 0.25f, mLocationPaint);
		canvas.drawText(distance, perX - mLocationPaint.measureText(distance) / 2.0f,
				perY + mTextHeight * 0.75f, mLocationPaint);
	}
}
